package answercard;

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.*;

/**
 * 答题卡识别
 * 1.用画图软件打开图片获取选择题区域最左上角像素坐标
 * 2.查询轮廓，并把轮廓面积大于300的取出来，表示填涂项
 * 3.根据图像坐标解释答案
 * @author chenkn
 * since 2018/12/18
 */
public class SimAsk {

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String[] args) {
        String src = "D:\\eclipse_wk\\opencv-master\\img\\a5.jpg";
        process(src);
    }
    static void process(String string){
        Mat img = Imgcodecs.imread(string);//读取图像
        System.out.println("img.width() = " + img.width());
        System.out.println("img.height() = " + img.height());
        Mat srcImage2 = new Mat();
        Mat srcImage3 = new Mat();
        Mat srcImage4 = new Mat();
        Mat srcImage5 = new Mat();
        Mat imag_ch2 = img.submat(new Rect(1600, 836, 1073, 853));
        Imgcodecs.imwrite("D://ask//imag_ch2.jpg", imag_ch2);//获取选择题轮廓
        //图片变成灰度图片,它将图像从一个颜色空间转换为另一个颜色空间。
        Imgproc.cvtColor(img, srcImage2, Imgproc.COLOR_RGB2GRAY);
//        Imgcodecs.imwrite("D://test1//result2.jpg", srcImage2);
        //图片二值化
//        Imgproc.adaptiveThreshold(srcImage2, srcImage3, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 255, 1);
        Imgproc.adaptiveThreshold(srcImage2, srcImage3, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 51, 10);
//        Imgcodecs.imwrite("D://test1//result3.jpg", srcImage3);
        //确定腐蚀和膨胀核的大小
        Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
//        //腐蚀操作
        Imgproc.erode(srcImage3, srcImage4, element);
//        Imgcodecs.imwrite("D://test1//result4.jpg", srcImage4);
        //膨胀操作
        Imgproc.dilate(srcImage3, srcImage5, element);
//        Imgcodecs.imwrite("D://test1//result5.jpg", srcImage5);
        //确定每张答题卡的ROI区域,xywh表示图片像素坐标
//        Mat imag_ch1 = srcImage5.submat(new Rect(1563, 784, 1230, 973));
        Mat imag_ch1 = srcImage5.submat(new Rect(1600, 836, 1073, 853));
        Imgcodecs.imwrite("D://ask//imag_ch1.jpg", imag_ch1);//获取选择题轮廓

        Vector<MatOfPoint> chapter1 = new Vector<>();
//        Imgproc.findContours(imag_ch1, chapter1, new Mat(), 3, 2,new Point());//查找轮廓
        Imgproc.findContours(imag_ch1, chapter1, new Mat(), 0, 2);//查找轮廓
        System.out.println("chapter1.size() = " + chapter1.size());
        List<RectComp> rectCompList = new ArrayList<>();
        for (int i = 0; i < chapter1.size(); i++) {
            MatOfPoint matOfPoint = chapter1.get(i);
            Rect rm = Imgproc.boundingRect(matOfPoint);
            RectComp ti = new RectComp(rm);
            //把轮廓宽度区间在 50 - 80 范围内的轮廓装进矩形集合
            if (ti.rm.width > 50 ) {
                Imgproc.drawContours(imag_ch2, chapter1, i, new Scalar(255,0,0), 3);
                Imgcodecs.imwrite("D://ask//"+i+".jpg", imag_ch2);//获取选择题轮廓
                rectCompList.add(ti);
            }
        }
        System.out.println(rectCompList.size());
        rectCompList.sort(Comparator.naturalOrder());
        System.out.println("rectCompList = " + rectCompList);
        TreeMap<Integer,String> listenAnswer = new TreeMap<>();
        for (int i = 0; i < rectCompList.size(); i++) {
            RectComp rect = rectCompList.get(i);
            System.out.println("rect.getRm() = " + rect.getRm());
           /* Mat mat = imag_ch2.submat(rect.rm);
            Imgproc.drawContours(imag_ch2, chapter1, i, new Scalar(0,0,255), 3);
            Imgcodecs.imwrite("D://ask//"+i+".jpg", mat);*/
            if (rect.getRm().area() > 3000) {
                if (rect.getRm().x < 160) {
                    listenAnswer.put(i, "A");
                } else if ((rect.getRm().x > 160) && (rect.getRm().x < 220)) {
                    listenAnswer.put(i, "B");
                } else if ((rect.getRm().x > 200) && (rect.getRm().x < 350)) {
                    listenAnswer.put(i, "C");
                } else if (rect.getRm().x > 350) {
                    listenAnswer.put(i, "D");
                }
            } else {
                listenAnswer.put(i, "未填写");
            }
        }
        StringBuilder resultValue = new StringBuilder("最终结果：试题编号-答案 ");
        listenAnswer.keySet().forEach(key-> resultValue.append("【").append(key + 1).append(":").append(listenAnswer.get(key)).append("】"));
        System.out.println("resultValue = " + resultValue);
        System.exit(0);

    }
}
